//
// Created by 11510 on 2024/6/12.
//
#include <vector>
#include <cstring>
#include "String.h"
using std::istream;
using std::vector;
/**
 * 无参构造
 */
String::String() {
    _pstr = new char [1]();
}

/**
 * c风格字符串构造
 */
String::String(const char *str) {
    _pstr = new char[strlen(str) + 1];
    strcpy(_pstr, str);
}

/**
 * 拷贝构造
 */
String::String(const String &str) {
    _pstr = new char[strlen(str._pstr) + 1];
    strcpy(_pstr, str._pstr);
}

/**
 * 析构函数
 */
String::~String() {
    if(nullptr != _pstr){
        delete[] _pstr;
        _pstr = nullptr;
    }
}

void String::print() {
    printf("%s\n", _pstr);
}

std::size_t String::size() const {
    return strlen(_pstr);
}

const char *String::c_str() const {
    return _pstr;
}

/**
 * 重载赋值运算符
 * @return
 */
String &String::operator=(const String & rhs) {
    /*不可自复制*/
    if(&rhs != this){
        /* 既然能赋值，说明这个对象已经构造出来了，所以直接delete */
        delete [] _pstr;
        _pstr = new char[strlen(rhs.c_str()) + 1]();
        strcpy(_pstr, rhs.c_str());
    }
    return *this;
}
/**
 * 重载赋值运算符，c风格字符串
 * @param rhs
 * @return
 */
String& String::operator=(const char *rhs) {
    /* 可以自复制，但是没必要*/
    if(strcmp(_pstr, rhs) != 0){
        delete [] _pstr;
        _pstr = new char[strlen(rhs) + 1]();
        strcpy(_pstr, rhs);
    }
    return *this;
}

/**
 * 重载取下标运算符，可赋值
 * 易错点：需要做越界判断
 * @param index
 * @return
 */
char &String::operator[](std::size_t index) {
    if(index > -1 && index < size()) {
        return _pstr[index];
    }

    static char nullchar ='\n';
    return nullchar;
}

/**
 * 重载取下标运算符，只读
 * @param index
 * @return
 */
const char &String::operator[](std::size_t index) const {
    if(index > -1 && index < size()) {
        return _pstr[index];
    }

    static char nullchar ='\n';
    return nullchar;
}


/**
 * 重载+=运算符,可以自拼接
 * @param rhs
 * @return
 */
String &String::operator+=(const String &rhs) {
    size_t len1 = size();
    size_t len2 = rhs.size();
    char *p = new char[len1 + len2 + 1]();
    strcpy(p, _pstr);
    strcat(p, rhs._pstr);

    delete [] _pstr;
    _pstr = p;

    return *this;
}

/**
 * 重载+=运算符 ，c风格
 * @param rhs
 * @return
 */
String &String::operator+=(const char *rhs) {
    size_t len1 = size();
    size_t len2 = strlen(rhs);

    char *p = new char[len1 + len2 + 1]();
    strcpy(p, _pstr);
    strcat(p, rhs);

    delete [] _pstr;
    _pstr = p;
    return *this;
}

/**
 * 类外友元函数形式重载 ==
 * @param lhs
 * @param rhs
 * @return
 */
bool operator==(const String &lhs, const String &rhs){
    return strcmp(lhs._pstr, rhs._pstr) == 0;
}

bool operator!=(const String &lhs, const String &rhs){
    return !(lhs == rhs);
}

/**
 * 重载输出流
 * @param os
 * @param s
 * @return
 */
std::ostream &operator<<(std::ostream &os, const String &s){
    if(s._pstr){
//        非空才能输出，安全起见，写上
        os << s._pstr;
    }
    return os;
}



/**
 * BUG 分配多少合适？未读完怎么办？
 * @param is
 * @param s
 * @return
 */
std::istream &operator>>(std::istream &is, String &s){
    if(s._pstr){
        delete[] s._pstr;
    }

    vector<char> buffer;
    char ch;
    while ((ch = is.get()) != '\n'){
        buffer.push_back(ch);
    }
    s._pstr = new char[buffer.size() + 1]();
    strncpy(s._pstr, &buffer[0], buffer.size());
    return is;
}

/**
 * 重载<运算符
 * @param lhs
 * @param rhs
 * @return
 */
bool operator<(const String &lhs, const String &rhs){
    int ret = strcmp(lhs._pstr, rhs._pstr);
    if (ret >= 0){
        return 0;
    }
    return 1;
}

bool operator>(const String &lhs, const String &rhs){
    return !(lhs < rhs);
}



bool operator<=(const String &lhs, const String &rhs){
    int ret = strcmp(lhs._pstr, rhs._pstr);
    if (ret > 0){
        return 0;
    }
    return 1;
}
bool operator>=(const String &lhs, const String &rhs){
    return !(lhs <= rhs);
}

/**
 * 重载+运算符，返回时调用了拷贝构造
 * @param lhs
 * @param rhs
 * @return
 */
String operator+(const String &lhs, const String &rhs){
//    此处有隐式类型转换
    String tmp = lhs;
    tmp += rhs;
    return tmp;
}
String operator+(const String &lhs, const char *rhs){
    return lhs + String(rhs);
}
String operator+(const char *lhs, const String &rhs){
    return String(lhs) + rhs;
}